<template>
  <div
    :class="[
      'card-wrapper',
      'cem-card',
      widgetStatusClass,
      isExpired || widgetStatus == 'concerned' || widgetStatus == 'warried'
        ? 'shake-fast-slightly'
        : '',
      // shake-fast
      // shake-fast-slightly
      // vibrate-fast
      // vibrate-fast-hard
    ]"
    @contextmenu.prevent="handleRightClick"
    @mouseenter="handleMouseMove"
    @mouseleave="handleMouseOut"
  >
    <!-- v-loading="isLoading" -->
    <!-- @mouseenter="handleMouseMove" -->
    <!-- @mouseleave="handleMouseOut" -->
    <!-- @mousemove="handleMouseMove" -->
    <!-- @mouseout="handleMouseOut" -->
    <transition name="el-fade-in-linear" mode="out-in">
      <div class="widget-cover" v-if="isHovering">
        <div class="menu-container">
          <div class="menu-item" @click="goto('/CEM/Current')">扇区建议</div>
          <div class="menu-item" @click="goto('/CEM/Input')">非民航计划</div>
          <div class="menu-item" @click="goto('/flow/GeneralChart')">
            常规图表
          </div>
          <!-- <div class="menu-item" @click="goto('/flow/AdvancedChart')">
            切片图表
          </div> -->
          <!-- <div class="menu-item" @click="goto('/CEM/Configuration')">
            参数设置
          </div> -->
          <div
            class="menu-item"
            style="font-size: 12px"
            @click="handleCompute(true)"
          >
            重新计算 ({{ getMyAge() }}秒前)
          </div>
        </div>
      </div>
      <div class="widget-content" v-else>
        <div class="widget-header">
          <span>CEM 扇区建议</span>
          <!-- <el-icon v-if="isLoading" class="is-loading">
            <Loading />
          </el-icon>
          <el-icon v-if="isComputing" class="is-loading">
            <Refresh />
          </el-icon> -->
        </div>
        <div class="widget-body content-error" v-if="isExpired">
          <!-- class="vibrate-hard" -->
          <el-icon :size="54"><CircleCloseFilled /></el-icon>
          <div style="padding: 6px 0">NTFM 数据已中断</div>
        </div>
        <div class="widget-body" v-else>
          <!-- <div
            style="
              display: flex;
              flex-direction: column;
              justify-content: center;
              align-items: center;
              width: 100%;
              height: 100%;
            "
          >
            <div style="padding: 12px; font-size: 18px">烂了</div>
            <div>￣□￣｜｜</div>
          </div> -->
        </div>
        <div class="widget-body" v-if="true">
          <el-scrollbar height="100px">
            <div class="line">
              <div>
                <div class="line">
                  <span style="padding-right: 4px">建议扇区数:</span>
                  <span style="font-weight: bolder; font-size: 16px">{{
                    supposedSectorCount
                  }}</span>
                </div>
                <div class="line">
                  <span style="padding-right: 4px">当前扇区数:</span>
                  <span style="font-weight: bolder; font-size: 16px">{{
                    realSectorCount
                  }}</span>
                </div>
              </div>

              <el-icon
                size="50"
                :class="[
                  isLoading || isComputing ? 'is-loading' : '',
                  // widgetStatus == 'fine' ? '' : 'shake-fast',
                  // shake-fast-slightly
                  // shake-fast
                  // vibrate-fast
                ]"
              >
                <!-- :class="[widgetStatus == 'fine' ? '' : 'vibrate-fast']" -->
                <Loading v-if="isLoading || isComputing" />
                <!-- <Refresh v-else-if="isComputing" /> -->
                <SuccessFilled v-else-if="widgetStatus == 'fine'" />
                <WarningFilled v-else-if="widgetStatus == 'concerned'" />
                <CircleCloseFilled v-else-if="widgetStatus == 'warried'" />
                <QuestionFilled v-else="widgetStatus == 'failed'" />
              </el-icon>
            </div>
            <div class="line line-comment">
              <div class="line" style="text-align: justify">
                建议: {{ comment }}
              </div>
            </div>
            <!-- <pre>{{ currentMode }}</pre> -->
            <!-- <pre>{{ currentAdvice }}</pre> -->
            <!-- <pre>{{ JSON.stringify(currentRecommend, null, 2) }}</pre> -->
          </el-scrollbar>
        </div>
        <div class="widget-footer footer-content">
          <pre>{{ activityStore.opMode }}</pre>
          <pre>{{ Math.round(dataSize / 100) / 10 }}kb</pre>
          <pre>{{ computeTime }}ms</pre>
          <!-- <pre>{{ currentMomentIndex }}</pre> -->
          <pre>{{
            dayjs(flowStore.begTime)
              .add(currentMomentIndex * 15, "minute")
              .format("HH:mm")
          }}</pre>
        </div>
      </div>
    </transition>
  </div>
</template>

<script setup>
import {
  ref,
  reactive,
  computed,
  onMounted,
  onUnmounted,
  h,
  nextTick,
} from "vue";
import { useRoute, useRouter } from "vue-router";
import { ElMessage, ElMessageBox, ElNotification } from "element-plus";
import axios from "axios";
import dayjs from "dayjs";

import useFlowStore from "@/store/flow.js";
import useSeatStore from "@/store/seat.js";
import useActivityStore from "@/store/activity.js";
import useCommonStore from "@/store/common.js";
import useCEMStore from "@/store/CEM.js";

import areaCompute from "../TryComputing/areaCompute.js";
import sectorCompute from "../TryComputing/sectorCompute.js";
import policyCompute from "../TryComputing/policyCompute.js";

import throttle from "@/utils/throttle.js";
import debounce from "@/utils/debounce.js";

const route = useRoute();
const router = useRouter();

const flowStore = useFlowStore();
const seatStore = useSeatStore();
const activityStore = useActivityStore();
const commonStore = useCommonStore();
const CEMStore = useCEMStore();

const isExpired = computed(() => flowStore.freshness > 600);

let myLastCompute = 0;
const myInterval = 5 * 1000;
const iNeedInterval = 50 * 1000;
const iMustInterval = 150 * 1000;
const mouseInterval = 10 * 1000;
const getMyAge = () => dayjs().diff(dayjs(myLastCompute), "second");

const source = computed(() => ({
  raw: flowStore.rawData,
  tags: flowStore.tags,
  begin: flowStore.begTime,
  areas: CEMStore.areas,
  sectors: CEMStore.sectors,
  length: flowStore.rawData.length,
  moments: new Array(flowStore.rawData.length).fill("").map((v, i, a) =>
    dayjs(flowStore.begTime)
      .add(15 * i, "minute")
      .format("HH:mm")
  ),
}));

// const areaResult = ref([]);
// const policyResult = ref([]);
// const sectorResult = ref([]);
// const computeTime = ref(0);
// const dataSize = ref(0);

const areaResult = computed(() => CEMStore.realCompute.areaResult);
const sectorResult = computed(() => CEMStore.realCompute.sectorResult);
const policyResult = computed(() => CEMStore.realCompute.policyResult);
const computeTime = computed(() => CEMStore.realCompute.computeTime);
const dataSize = computed(() => CEMStore.realCompute.dataSize);

const sourceCache = ref("");
const isComputing = ref(false);
// const updateTime = ref("");

const handleCompute = (force = false) => {
  // 运行模式修复前关闭此功能
  // return false;
  if (isExpired.value) {
    myLog("Flow data expired!!!");
    return null;
  }
  if (sourceCache.value == JSON.stringify(source.value) && !force) {
    myLog("Flow data no change~");
    return null;
  } else {
    sourceCache.value == JSON.stringify(source.value);
  }
  myLog("Going to compute");
  let startTime = new Date().getTime();
  isComputing.value = true;
  let t0 = new Date().getTime();
  let r1 = areaCompute(source.value);
  let r2 = sectorCompute({ areaResult: r1, ...source.value });
  let r3 = policyCompute(r2, source.value.length, false);
  let s = Math.round(
    (JSON.stringify(r1).length +
      JSON.stringify(r2).length +
      JSON.stringify(r3).length) /
      1000
  );
  let t = new Date().getTime() - t0;
  // areaResult.value = r1;
  // sectorResult.value = r2;
  // policyResult.value = r3;
  // computeTime.value = t;
  // dataSize.value = s;
  let result = {
    areaResult: r1,
    sectorResult: r2,
    policyResult: r3,
    computeTime: t,
    dataSize: s,
  };
  CEMStore.realCompute = result;
  isComputing.value = false;
  // updateTime.value = dayjs();
  myLastCompute = new Date().getTime();
  myLog("Computing finished in " + (new Date().getTime() - startTime) + "ms");
  return result;
};
const currentMode = computed(
  () => "NN"
  // seatStore.seatStatusFull
  //   ? seatStore.seatStatusFull.filter((cell) => cell.seatType == "运行方向")[0]
  //       .logicSectorCode +
  //     (activityStore.militaryStatus.filter((cell) =>
  //       (cell.arrField + cell.depField + cell.unit).includes("温江")
  //     ).length > 0
  //       ? "WJ"
  //       : "")
  //   : ""
);

const currentMomentIndex = computed(() => {
  if (currentAdvice.value) {
    for (let i = 0; i < currentAdvice.value.recommend.length; i++) {
      let target = dayjs(flowStore.begTime).add(i * 15, "minute");
      if (dayjs().diff(target, "minute") <= 15) {
        return i;
      }
    }
  }
  return null;
});
const currentAdvice = computed(() =>
  policyResult.value
    ? policyResult.value.filter((item) => item.mode == currentMode.value)[0]
    : null
);
const currentRecommend = computed(() => {
  if (currentAdvice.value) {
    myLog("widget currentMomentIndex:" + currentMomentIndex.value);
    return currentAdvice.value.recommend[currentMomentIndex.value];
  } else {
    return null;
  }
});
const seatStatus = computed(() =>
  seatStore.seatStatus.filter(
    (item) =>
      item.sectorCodes.length > 0 && item.orgGroup == "TMA" && item.sectorYes
  )
);
const realSectorCount = computed(() =>
  seatStatus.value ? seatStatus.value.length : 0
);
const supposedSectorCount = computed(() =>
  currentRecommend.value && currentRecommend.value.areas
    ? currentRecommend.value.areas.length
    : 0
);
const widgetStatus = computed(() =>
  seatStatus.value &&
  currentRecommend.value &&
  currentRecommend.value.areas &&
  !isExpired.value
    ? seatStatus.value.length >= currentRecommend.value.areas.length
      ? "fine"
      : "concerned"
    : "failed"
);
const widgetStatusClass = computed(() => "widget-status-" + widgetStatus.value);

const isLoading = ref(false);
const isHovering = ref(false);
const handleRightClick = (e) => {
  ElMessageBox({
    title: "",
    message: h("pre", null, JSON.stringify(seatStatus.value, null, 2)),
  });
};
const handleMouseMove = (e) => {
  // throttle(toggleHovering(true), 1000, false);
  toggleHovering(true);
};
const handleMouseOut = (e) => {
  // throttle(toggleHovering(false), 1000, false);
  toggleHovering(false);
};
const toggleHovering = (val) => {
  isHovering.value = val;
};

const goto = (path) => {
  router.push(path);
};

const show = ref(false);
const refreshCard = async () => {
  show.value = false;
  await nextTick();
  show.value = true;
};

const comment = computed(() => {
  let list = new Array();
  if (
    seatStatus.value &&
    currentRecommend.value &&
    currentRecommend.value.areas
  ) {
    if (seatStatus.value.length >= currentRecommend.value.areas.length) {
      let maxIndex = 0;
      let max = currentRecommend.value.areas.length;
      for (let i = 1; i <= 4 && i < currentAdvice.value.recommend.length; i++) {
        if (
          max <
          currentAdvice.value.recommend[currentMomentIndex.value + i].areas
            .length
        ) {
          max =
            currentAdvice.value.recommend[currentMomentIndex.value + i].areas
              .length;
          maxIndex = i;
        }
      }
      if (max < seatStatus.value.length) {
        list.push(`合并为 ${max} 个扇区`);
      } else if (max > seatStatus.value.length) {
        list.push(
          `于 ${dayjs(flowStore.begTime)
            .add((currentMomentIndex.value + maxIndex) * 15, "minute")
            .format("HH:mm")} 开放  ${max} 个扇区`
        );
      }
      let max2 = 0;
      let max2Index = -1;
      for (let i = 5; i <= 8 && i < currentAdvice.value.recommend.length; i++) {
        if (
          max2 <
          currentAdvice.value.recommend[currentMomentIndex.value + i].areas
            .length
        ) {
          max2 =
            currentAdvice.value.recommend[currentMomentIndex.value + i].areas
              .length;
          max2Index = i;
        }
      }
      if (max2 < max) {
        list.push(
          `于 ${dayjs(flowStore.begTime)
            .add((currentMomentIndex.value + max2Index) * 15, "minute")
            .format("HH:mm")} 合并为 ${max2} 个扇区`
        );
      } else if (max2 > max) {
        list.push(
          `于 ${dayjs(flowStore.begTime)
            .add((currentMomentIndex.value + max2Index) * 15, "minute")
            .format("HH:mm")} 开放 ${max2} 个扇区`
        );
      }
    } else {
      list.push("尽快开放扇区!");
      let max = currentRecommend.value.areas.length;
      let max2 = 1;
      let max2Index = -1;
      for (let i = 1; i <= 8 && i < currentAdvice.value.recommend.length; i++) {
        if (
          max2 <
          currentAdvice.value.recommend[currentMomentIndex.value + i].areas
            .length
        ) {
          max2 =
            currentAdvice.value.recommend[currentMomentIndex.value + i].areas
              .length;
          max2Index = i;
        }
      }
      if (max2 < max) {
        list.push(
          `于 ${dayjs(flowStore.begTime)
            .add((currentMomentIndex.value + max2Index) * 15, "minute")
            .format("HH:mm")} 合并为 ${max2} 个扇区`
        );
      } else if (max2 > max) {
        list.push(
          `于 ${dayjs(flowStore.begTime)
            .add((currentMomentIndex.value + max2Index) * 15, "minute")
            .format("HH:mm")} 开放 ${max2} 个扇区`
        );
      }
    }
  }
  return (list.length > 0 ? list.join(", ") : "无") + "。";
});

const myLog = (msg = "") => {
  return null;
  console.log("[CEM Compute][" + dayjs().format("HH:mm:ss") + "]", msg);
};

const paramTimer = ref(null);
const computeTimer = ref(null);

onMounted(() => {
  myLog("Widget loaded");
  isLoading.value = true;
  CEMStore.loadData()
    .then(() => {
      isLoading.value = false;
      handleCompute();
      refreshCard();
      myLog("First computing finished");
      // myLastCompute = new Date().getTime();
      if (!computeTimer.value) {
        computeTimer.value = setInterval(() => {
          let nowTime = new Date().getTime();
          let iNeed = nowTime - myLastCompute > iNeedInterval;
          let iMust = nowTime - myLastCompute > iMustInterval;
          let isMouseFree = nowTime - commonStore.lastMouseMove > mouseInterval;
          if (iNeed) {
            myLog("Need to refresh");
            if (isMouseFree || iMust) {
              handleCompute();
              refreshCard();
              // myLastCompute = new Date().getTime();
              myLog(iMust ? "Forced to refresh!" : "Refreshed!");
            } else {
              myLog("Ignored because mouse bussy");
            }
          } else {
            myLog("No need to refresh");
          }
        }, myInterval);
      }
    })
    .catch(() => (isLoading.value = false));
  if (!paramTimer.value) {
    paramTimer.value = setInterval(() => CEMStore.loadData(), 10 * 1000);
  }
});

onUnmounted(() => {
  clearInterval(paramTimer.value);
  clearInterval(computeTimer.value);
  paramTimer.value = null;
  computeTimer.value = null;
});
</script>

<style scoped>
@import "@/styles/card.css";
@import "@/styles/vibrate.css";
@import "@/styles/shake.css";
.cem-card {
  font-size: 12px;
  text-shadow: 0 1px 4px rgba(0, 0, 0, 0.4);
  background-color: #eeeeee;
  overflow: hidden;
  position: relative;
}
.widget-header {
  position: absolute;
  top: 0;
  height: 30px;
  left: 0;
  right: 0;
  border-bottom: 1px solid #8884;
  display: flex;
  align-items: center;
  /* justify-content: space-between; */
  justify-content: center;
  font-size: 14px;
  font-weight: bolder;
}
.widget-body {
  position: absolute;
  top: 30px;
  bottom: 30px;
  left: 0;
  right: 0;
  /* border: 1px solid #8884; */
}
.widget-footer {
  position: absolute;
  bottom: 0;
  height: 30px;
  left: 0;
  right: 0;
  border-top: 1px solid #8884;
  display: flex;
  align-items: center;
  /* justify-content: space-between; */
  justify-content: center;
}

.footer-content > * {
  margin-left: 6px;
}
.footer-content > first-child {
  margin-left: 0px;
}
.widget-status-fine {
  background: linear-gradient(135deg, #3282b8, #29c6cd);
}
.widget-status-concerned {
  background: linear-gradient(135deg, #f67280, #9b4f6a);
}
.widget-status-warried {
  background: linear-gradient(135deg, #d2413f, #e76f51);
}
.widget-status-failed {
  background: linear-gradient(135deg, #525252, #a3a3a3);
}
.line {
  width: 100%;
  display: flex;
  align-items: center !important;
  justify-content: space-between;
  padding: 1px 4px;
}

/* .line > * {
  margin-left: 6px;
}

.line > first-child {
  margin-left: 0;
} */

.line-comment {
  margin-top: 3px;
  padding-top: 3px;
  border-top: 1px solid #8884;
}

.widget-cover {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  /* z-index: 999; */
  /* backdrop-filter: blur(10px); */
}
.widget-content {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  /* z-index: 999; */
}

.menu-container {
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
}

.menu-container > .menu-item {
  /* width: 100%; */
  /* height: 100%; */
  flex: 1;
  transition: all 0.3s ease-in-out;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 14px;
  font-weight: bolder;
  /* color: #eee; */
  /* color: #fffc; */
  border-bottom: 1px solid #8884;
}

.menu-container > .menu-item:hover {
  background-color: #0004;
  /* color: #ffff; */
}

.menu-container > .menu-item:last-child {
  border-bottom: none;
}

.content-error {
  display: flex;
  justify-content: center;
  align-items: center;
  flex-direction: column;
}
</style>
